package com.hzy.fivepalace.admin.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hzy.fivepalace.admin.async.AdminAsyncFactory;
import com.hzy.fivepalace.admin.controller.base.BaseController;
import com.hzy.fivepalace.admin.dao.addCoupons;
import com.hzy.fivepalace.common.type.CouponsQueryTypeEnums;
import com.hzy.fivepalace.common.type.CouponsStatusEnums;
import com.hzy.fivepalace.common.type.WhetherTypeEnum;
import com.hzy.fivepalace.common.util.ObjectUtils;
import com.hzy.fivepalace.common.util.ResponseUtil;
import com.hzy.fivepalace.common.util.TableDataInfo;
import com.hzy.fivepalace.db.dao.DtsCommentMapper;
import com.hzy.fivepalace.db.dao.DtsCouponMapper;
import com.hzy.fivepalace.db.dao.ex.CommentMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsCouponUserMapperEx;
import com.hzy.fivepalace.db.dao.ex.DtsGoodsMapperEx;
import com.hzy.fivepalace.db.domain.*;
import com.hzy.fivepalace.db.service.DtsUserService;
import com.hzy.fivepalace.db.vo.wx.WxGoodsCommentVo;
import com.hzy.fivepalace.db.vo.wx.WxUserCouponsVo;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 优惠券服务
 */
@Service
public class AdminCouponService extends BaseController {

    @Resource
    private DtsCouponUserMapperEx couponUserMapperEx;

    @Resource
    private DtsCouponMapper couponMapper;

    @Resource
    private DtsUserService userService;

    @Resource
    private Redisson redisson;

    @Autowired
    private AdminAsyncFactory asyncFactory;


    /**
     * 获取优惠券列表
     *
     * @param page
     * @param size
     * @param couponsName
     * @return
     */
    public TableDataInfo getCouponsList(Integer page, Integer size, String couponsName) {
        DtsCouponExample example = new DtsCouponExample();
        example.setOrderByClause("add_time desc");
        if (StringUtils.isBlank(couponsName)) {
            example.createCriteria().andDeletedEqualTo(false).andStatusEqualTo((short) 0);
        } else {
            example.createCriteria().andDeletedEqualTo(false).andNameLike("%" + couponsName + "%").andStatusEqualTo((short) 0);
        }
        Page p = PageHelper.startPage(page, size, true);
        List<DtsCoupon> list = couponMapper.selectByExample(example);
        List<Map<String, Object>> couponsList = new ArrayList<>();
        list.forEach(item -> {
            Map<String, Object> vo = new HashMap<>();
            vo.put("id", item.getId());
            //优惠券名称
            vo.put("couponsName", item.getName());
            //最低使用金额
            vo.put("minUseMoney", item.getMin());
            //优惠券金额
            vo.put("money", item.getDiscount());
            //有效期天数
            vo.put("days", item.getDays());
            //更新时间
            vo.put("updateTime", item.getUpdateTime());
            //创建时间
            vo.put("addTime", item.getAddTime());

            //查询派发数量
            DtsCouponUserExample receiveCountExample = new DtsCouponUserExample();
            receiveCountExample.createCriteria().andDeletedEqualTo(false).andCouponIdEqualTo(item.getId());
            //派发数量
            vo.put("payoutCount", couponUserMapperEx.countByExample(receiveCountExample));

            //查询使用数量
            DtsCouponUserExample userCountExample = new DtsCouponUserExample();
            userCountExample.createCriteria().andDeletedEqualTo(false).andCouponIdEqualTo(item.getId()).andStatusEqualTo((short) 1);
            //使用数量
            vo.put("useCount", couponUserMapperEx.countByExample(userCountExample));
            couponsList.add(vo);
        });
        return TableDataInfo.getDataTable(couponsList, p.getTotal());
    }

    /**
     * 用户优惠券列表
     *
     * @param page
     * @param size
     * @param status 状态：0未使用，1已失效
     * @param userId
     * @param id
     * @return
     */
    public TableDataInfo getUserCouponsList(Integer page, Integer size, Integer status, Integer userId, Integer id) {
        if (null != status) {
            CouponsQueryTypeEnums couponsQueryTypeEnums = CouponsQueryTypeEnums.getEnum(status.intValue());
            if (null == couponsQueryTypeEnums) {
                return TableDataInfo.errorDataTable("查询类型错误");
            }
        }
        Page p = PageHelper.startPage(page, size, true);
        List<WxUserCouponsVo> list = couponUserMapperEx.getUserCouponsList(status, userId, id);
        List<Map<String, Object>> couponsList = new ArrayList<>();
        list.forEach(item -> {
            if (item.getStatus().intValue() == CouponsStatusEnums.TYPE0.getId() && !LocalDateTime.now().isAfter(item.getEndTime())) {//未使用并且未过期的券计算距离到期还剩多少天
                long days = Duration.between(LocalDateTime.now(), item.getEndTime()).toDays();
                item.setEndDays(days > 0 ? days + "天后到期" : "即将到期");
            } else if (item.getStatus().intValue() == CouponsStatusEnums.TYPE1.getId()) {
                item.setEndDays("已使用");
                item.setStatus(CouponsStatusEnums.TYPE1.getId());
            } else {
                item.setEndDays("已过期");
                item.setStatus(CouponsStatusEnums.TYPE2.getId());
            }
            Map<String, Object> vo = ObjectUtils.convertToMap(item);
            //获取用户信息
            vo.put("userInfo", userService.getUserNickNameAndPhoneAndAvatar(item.getUserId()));
            couponsList.add(vo);
        });
        return TableDataInfo.getDataTable(couponsList, p.getTotal());
    }

    /**
     * 派发优惠券-单个
     *
     * @param userId
     * @param id
     * @return
     */
    public Object payoutCouponsSingle(Integer userId, Integer id) {
        RLock lock = redisson.getLock("admin_payoutCouponsSingle_" + userId + id);
        if (lock.isLocked()) {
            return ResponseUtil.frequent("其他管理人员操作中,请稍后再试");
        }
        lock.lock(30, TimeUnit.SECONDS);

        DtsCoupon coupon = couponMapper.selectByPrimaryKey(id);
        if (null == coupon || coupon.getDeleted() || coupon.getStatus().intValue() != 0) {
            lock.unlock();
            return ResponseUtil.fail("优惠券不存在或已被删除");
        }
        DtsUser user = userService.findById(userId);
        if (null == user | user.getDeleted()) {
            lock.unlock();
            return ResponseUtil.fail("接收用户不存在");
        }
        DtsCouponUser couponUserAdd = new DtsCouponUser();
        couponUserAdd.setCouponId(id);
        couponUserAdd.setAddTime(LocalDateTime.now());
        couponUserAdd.setUpdateTime(LocalDateTime.now());
        couponUserAdd.setUserId(userId);
        couponUserAdd.setStatus((short) CouponsStatusEnums.TYPE0.getId());
        couponUserAdd.setStartTime(LocalDateTime.now());
        couponUserAdd.setEndTime(LocalDateTime.now().plusDays(coupon.getDays()));
        couponUserAdd.setDeleted(false);
        couponUserMapperEx.insertSelective(couponUserAdd);
        lock.unlock();
        return ResponseUtil.ok("派发成功", null);
    }

    /**
     * 派发优惠券-所有
     *
     * @param id
     * @return
     */
    public Object payoutCouponsAll(Integer id) {
        RLock lock = redisson.getLock("admin_payoutCouponsAll_" + id);
        if (lock.isLocked()) {
            return ResponseUtil.frequent("其他管理人员操作中,请稍后再试");
        }
        lock.lock(30, TimeUnit.SECONDS);

        DtsCoupon coupon = couponMapper.selectByPrimaryKey(id);
        if (null == coupon || coupon.getDeleted() || coupon.getStatus().intValue() != 0) {
            lock.unlock();
            return ResponseUtil.fail("优惠券不存在或已被删除");
        }
        DtsCouponUser couponUserAdd = new DtsCouponUser();
        couponUserAdd.setCouponId(id);
        couponUserAdd.setAddTime(LocalDateTime.now());
        couponUserAdd.setUpdateTime(LocalDateTime.now());
        couponUserAdd.setStatus((short) CouponsStatusEnums.TYPE0.getId());
        couponUserAdd.setStartTime(LocalDateTime.now());
        couponUserAdd.setEndTime(LocalDateTime.now().plusDays(coupon.getDays()));
        couponUserAdd.setDeleted(false);
        asyncFactory.asyncPayoutCouponsAll(couponUserAdd);
        lock.unlock();
        return ResponseUtil.ok("派发成功", null);
    }

    /**
     * 作废已派发未使用的优惠券
     *
     * @param id
     * @return
     */
    public Object withdrawAllPayout(Integer id) {
        RLock lock = redisson.getLock("admin_withdrawAllPayout_" + id);
        if (lock.isLocked()) {
            return ResponseUtil.frequent("其他管理人员操作中,请稍后再试");
        }
        lock.lock(30, TimeUnit.SECONDS);

        DtsCoupon coupon = couponMapper.selectByPrimaryKey(id);
        if (null == coupon) {
            lock.unlock();
            return ResponseUtil.fail("优惠券不存在或已被删除");
        }
        asyncFactory.asyncWithdrawAllPayout(id);
        lock.unlock();
        return ResponseUtil.ok("", null);
    }

    /**
     * 新增优惠券
     *
     * @param dto
     * @return
     */
    public Object addCoupons(addCoupons dto) {
        Integer adminId = getAdminId();
        RLock lock = redisson.getLock("admin_addCoupons_" + adminId);
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);
        if (StringUtils.isBlank(dto.getCouponsName())) {
            lock.unlock();
            return ResponseUtil.fail("优惠券名称不能为空");
        }
        if (null == dto.getMinUseMoney()) {
            dto.setMinUseMoney(new BigDecimal(0));
        }
        if (null == dto.getMoney()) {
            lock.unlock();
            return ResponseUtil.fail("优惠券金额不能为空");
        }
        if (dto.getMoney().compareTo(new BigDecimal(0)) <= 0) {
            lock.unlock();
            return ResponseUtil.fail("优惠券金额不能小于等于0");
        }

        if (null == dto.getDays() || dto.getDays() <= 0) {
            dto.setDays(30);
        }

        DtsCoupon coupon = new DtsCoupon();
        coupon.setName(dto.getCouponsName());
        coupon.setDays(dto.getDays().shortValue());
        coupon.setMin(dto.getMinUseMoney());
        coupon.setDiscount(dto.getMoney());
        coupon.setDeleted(false);
        coupon.setAddTime(LocalDateTime.now());
        coupon.setUpdateTime(LocalDateTime.now());
        coupon.setStatus((short) 0);
        couponMapper.insertSelective(coupon);
        lock.unlock();
        return ResponseUtil.ok("新增成功", null);
    }
}
